/**
 * @fileoverview   dom/gain 获取元素模块，包括查询，遍历，过滤等

 * @date: 11-11-4
 * @time: 上午10:33
 * @author 2kid
 * @version 0.001
 */

/**
 *
 *
 * 方法：
 * dom.query
 * dom.prototype.find
 * dom.prototype.get
 * dom.prototype.eq
 * dom.prototype.slice
 * dom.prototype.each
 * dom.prototype.filter
 * dom.prototype.next
 * dom.prototype.nextAll
 * dom.prototype.prev
 * dom.prototype.prevAll
 * dom.prototype.children
 * dom.prototype.parent
 *
 *
 */
F.reg('dom/gain', function (f, dom) {
    var win = window, doc = win['document'], docElement = doc.documentElement;

    f.extend(dom, {
        /**
         * @name F.Dom.query
         * @function
         * @namespace css 选择器 默认支持 id,class,tag,子代选择器。如：#abc div ,在支持querySelectorAll，可支持所有的css选择器
         * @param seletor css选择器字符串，window,document,Nodelist,Element
         * @return { Object } Dom对象
         * @example
         * 例子：
         * 1.
         * //选择所有的a标签
         * dom.query('a');
         * 2.
         * //
         * dom.query(document.getElementsByTagName('a'));
         * 3.
         * //
         * dom.query(document.getElementById('abc'));
         * 4.
         * dom.query(document);
         * 5.
         * dom.query(dom.query('a'));
         */

        query:function (seletor) {
            if (f.type(seletor, 'string')) {
                return  new dom(f.merge([], dom.select.exec(f.trim(seletor))));
            } else if (seletor.nodeType || seletor.nodeType === dom.NodeType.ELEMENT_NODE ||
                seletor.nodeType === dom.NodeType.DOCUMENT_NODE || dom.iswin(seletor)) {
                return new dom([seletor]);
            } else if ('item' in seletor && 'length' in seletor) {
                return new dom(f.merge([], seletor));
            } else {
                return seletor;
            }


        }
    }, true);
    f.extend(dom, {
        /**
         * @name F.Dom.prototype.find
         * @function
         * @namespace css 选择器 同query
         * @param seletor
         * @return {Object} Dom对象
         * @example
         * 例子：
         * 1.
         * //选择所有div的a标签
         * dom.query('div').find('a');
         */
        find:function (seletor) {
            return  new dom(f.merge([], dom.select.exec(seletor, this.get())));
        },
        /**
         * @name F.Dom.prototype.eq
         * @function
         * @namespace 返回索引元素的对象
         * @param {Number} i  从0开始，返回索引元素的Dom对象
         * @return {Object} Dom对象
         * @example
         * 例子：
         * 1.
         * //返回第一个div的Dom对象
         * dom.query('div').eq(0);
         */
        eq:function (i) {
            if (f.type(i, 'number')) {
                return new dom([this.get(i)]);
            }
            return this;
        },
        /**
         * @name F.Dom.prototype.slice
         * @function
         * @namespace 获取包含当前节点列表选定范围内原生节点的 dom 对象
         * @param {Number} start  规定从何处开始选取。如果是负数，那么它规定从数组尾部开始算起的位置。也就是说，-1 指最后一个元素，-2 指倒数第二个元素，以此类推。
         * @param {Number} end  可选 范围结束位置, 忽略的话结束坐标为当前列表末尾
         * @return {Object} Dom对象
         * @example
         * 例子：
         * 1.
         * //[0,1,2,3,4,5,6]
         * //返回索引起始为2到4的元素，包括2，不包括4.
         * dom.query('div').slice(2，4);
         */
        slice:function (start, end) {
            return new dom(Array.prototype.slice.apply(this, arguments));
        },
        /**
         * @name F.Dom.prototype.concat
         * @function
         * @namespace 拼接Dom对象、
         * @param d Dom对象
         * @return {Object} Dom对象
         * @example
         * 例子：
         * 1.
         *
         * var c=dom.query('div').concat(dom.query('a'));
         * //c 是div
         *
         */
        concat:function (d) {
            return new dom(Array.prototype.concat.call(this.get(), d.get()));
        },
        /**
         * @name F.Dom.prototype.each
         * @function
         * @namespace 循环每个元素
         * @param fn (item,i)  函数中的this指向每个元素对应的 Dom对象，item元素，i对应索引
         * @return {Object} Dom对象
         * @example
         * 例子：
         * 1.
         * dom.query('a').each(function(){
         *     if(this.hasclass('aa')){
         *         alert('a has classname  aa!');
         *     }
         * })
         */
        each:function (fn) {
            var thatelem = this.get();
            f.each(thatelem, function (item, i) {
                //使调用函数的this为当前元素的dom对象
                this.set([item]);
                fn.call(this, item, i);
            }, this);
            this.set(thatelem);
            return this;
        },
        /**
         * @name F.Dom.prototype.filter
         * @function
         * @namespace 过滤已选择的元素
         * @param {String | Function } expr    String过滤表达式|Function自定义过滤函数
         * @return {Object} Dom对象
         * @example
         * 例子：
         * 1.
         * //过滤所有奇数
         * dom.query('a').filter(':odd');
         * 2.
         * //过滤所有 aa类 的元素
         * dom.query('a').filter(function(){
         *     return this.hasclass('aa');
         * });
         */
        filter:function (expr) {
            var elem = [], thatelem = this.get();
            if (f.type(expr, 'string')) {
                elem = dom.filter.exec(expr, this.get());
            } else if (f.type(expr, 'function')) {
                elem = f.filter(thatelem, function (item, i) {
                    this.set([item]);
                    return expr.call(this, item, i);
                }, this);

            }
            this.set(thatelem);
            return new dom(f.merge([], elem));

        },
        /**
         * @name F.Dom.prototype.next
         * @function
         * @namespace 后一个同辈元素
         * @return {Object} Dom对象
         * @example
         * 例子：
         * &lt;div&gt;
         *     &lt;p&gt;&lt;/p&gt;
         *     &lt;a herf=""&gt;aa&lt;/a&gt;
         *     &lt;a herf=""&gt;bb&lt;/a&gt;
         * &lt;/div&gt;
         * &lt;div&gt;
         *     &lt;p&gt;&lt;/p&gt;
         *     &lt;a herf=""&gt;cc&lt;/a&gt;
         *     &lt;a herf=""&gt;dd&lt;/a&gt;
         * &lt;/div&gt;
         * //取得&lt;a herf=""&gt;aa&lt;/a&gt;,&lt;a herf=""&gt;cc&lt;/a&gt;
         * dom.query('div p').next();
         */
        next:function () {
            return this._wraker('nextSibling', false);
        },
        /**
         * @name F.Dom.prototype.nextAll
         * @function
         * @namespace 所有在当前元素后面同辈元素
         * @return {Object} Dom对象
         * @example
         * 例子：
         * &lt;div&gt;
         *     &lt;p&gt;&lt;/p&gt;
         *     &lt;a herf=""&gt;aa&lt;/a&gt;
         *     &lt;a herf=""&gt;bb&lt;/a&gt;
         * &lt;/div&gt;
         * &lt;div&gt;
         *     &lt;p&gt;&lt;/p&gt;
         *     &lt;a herf=""&gt;cc&lt;/a&gt;
         *     &lt;a herf=""&gt;dd&lt;/a&gt;
         * &lt;/div&gt;
         * //取得&lt;a herf=""&gt;aa&lt;/a&gt;,&lt;a herf=""&gt;bb&lt;/a&gt;，&lt;a herf=""&gt;cc&lt;/a&gt;,&lt;a herf=""&gt;dd&lt;/a&gt;
         * dom.query('div p').nextall();
         */
        nextall:function () {
            return this._wraker('nextSibling', true);
        },
        /**
         * @name F.Dom.prototype.prev
         * @function
         * @namespace 前一个同辈元素
         * @return {Object} Dom对象
         * @example
         * 参考 next
         */
        prev:function () {
            return this._wraker('previousSibling', false);
        },
        /**
         * @name F.Dom.prototype.prevall
         * @function
         * @namespace 所有在当前元素前面同辈元素
         * @return {Object} Dom对象
         * @example
         * 参考 nextall
         */
        prevall:function () {
            return this._wraker('previousSibling', true);
        },
        /**
         * @name F.Dom.prototype.children
         * @function
         * @namespace 当前元素的子元素
         * @return {Object} Dom对象
         */
        children:function () {
            var tmpdom,
                thatelem = this.get(),
                tmpelem = [];
            f.each(thatelem, function (ele) {
                tmpelem.push(ele.firstChild);
            }, this);
            this.set(tmpelem);
            tmpdom = this._wraker('nextSibling', true);
            this.set(thatelem);
            return tmpdom;
        },
        /**
         * @name F.Dom.prototype.parent
         * @function
         * @namespace 当前元素的父元素
         * @return {Object} Dom对象
         */
        parent:function () {
            var elem = [];
            f.each(this.get(), function (ele) {
                if (f.inarray(elem, ele.parentNode) === -1) {
                    elem.push(ele.parentNode);
                }
            }, this);
            return new dom(elem);
        },
        /**
         * @function
         * @param dir
         * @param {Boolean} unlimit 无限制 true无限
         */
        _wraker:function (dir, unlimit) {
            var elem = [], thatelem = this.get();

            f.each(thatelem, function (ele) {
                do {
                    ele = ele[dir];
                    if (ele && ele.nodeType === dom.NodeType.ELEMENT_NODE) {
                        elem.push(ele);
                    }

                } while (ele && (unlimit || ele.nodeType !== dom.NodeType.ELEMENT_NODE));
            });
            return new dom(elem);
        }
    });


    return dom;
}, {
    requires:[
        'dom/select',
        'dom/filter'
    ]
});